package com.action.dialect.processor;

import com.action.entity.Organization;
import com.action.entity.Resource;
import com.action.entity.Role;
import com.action.service.OrganizationService;
import com.action.service.ResourceService;
import com.action.service.RoleService;
import com.action.spring.SpringContextUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.engine.AttributeName;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.templatemode.TemplateMode;

import java.util.List;

import static at.pollux.thymeleaf.shiro.processor.ThymeleafFacade.evaluateAsStringsWithDelimiter;
import static at.pollux.thymeleaf.shiro.processor.ThymeleafFacade.getRawValue;

/**
 * Created by tang on 2018/1/25.
 */
public class ReplaceStringTagProcessor extends AbstractAttributeTagProcessor {
    private static final String ATTRIBUTE_NAME = "replace_string";//标签名
    private static final int PRECEDENCE = 10000;//优先级
    private static final String DELIMITER = ",";


    private final static String ROLE_LIST = "role_list";
    private final static String ORGANIZATION_LIST = "organization_list";
    private final static String RESOURCE_LIST = "resource_list";
    private final static String RESOURCE_LIST_VALUE = "resource_list_value";
    private final static String ROLE_NAME = "role_name";
    private final static String ORGANIZATION_NAME = "organization_name";
    private final static String RESOURCE_NAME = "resource_name";
    private final static String VALUE = "value";
    private final static String TD = "td";


    public ReplaceStringTagProcessor(String dialectPrefix) {
        super(
                TemplateMode.HTML, // 处理thymeleaf 的模型
                dialectPrefix, // 标签前缀名
                null, // No tag name: match any tag name
                false, // No prefix to be applied to tag name
                ATTRIBUTE_NAME, // 标签前缀的 属性 例如：< risk:sansiEncrypt="">
                true, // Apply dialect prefix to attribute name
                PRECEDENCE, // Precedence (inside dialect's precedence)
                true); // Remove the matched attribute afterwards
    }

    /**
     * context 页面上下文
     * tag  标签
     */
    @Override
    protected void doProcess(ITemplateContext context,
                             IProcessableElementTag tag, AttributeName attributeName,
                             String attributeValue, IElementTagStructureHandler structureHandler) {

        final IModelFactory modelFactory = context.getModelFactory();
        final IModel model = modelFactory.createModel();
        final String rawValue = getRawValue(tag, attributeName);
        //方法类型
        String type = null;
        //方法参数
        String exper = null;
        if (!StringUtils.isEmpty(rawValue)) {
            type = rawValue.split(":")[0];  //获取类型
            exper = rawValue.split(":")[1]; //获取表达式
        }

        //调用api将${xx.xx}转换为对应数据
        final List<String> values = evaluateAsStringsWithDelimiter(context, exper, DELIMITER);


        if (ROLE_LIST.equals(type)) {
            model.add(modelFactory.createOpenElementTag(TD));
            model.add(modelFactory.createText(roleList(values)));
            model.add(modelFactory.createCloseElementTag(TD));
        } else if (ORGANIZATION_LIST.equals(type)) {
            model.add(modelFactory.createOpenElementTag(TD));
            model.add(modelFactory.createText(organizationList(values)));
            model.add(modelFactory.createCloseElementTag(TD));
        } else if (RESOURCE_LIST.equals(type)) {
            model.add(modelFactory.createOpenElementTag(TD));
            model.add(modelFactory.createText(resourceList(values)));
            model.add(modelFactory.createCloseElementTag(TD));
        } else if (ROLE_NAME.equals(type)) {
            model.add(modelFactory.setAttribute(tag, VALUE, roleName(values)));
        } else if (ORGANIZATION_NAME.equals(type)) {
            model.add(modelFactory.setAttribute(tag, VALUE, organizationName(values)));
        } else if (RESOURCE_NAME.equals(type)) {
            model.add(modelFactory.setAttribute(tag, VALUE, resourceName(values)));
        } else if (RESOURCE_LIST_VALUE.equals(type)) {
            model.add(modelFactory.setAttribute(tag, VALUE, resourceList(values)));
        }
        structureHandler.replaceWith(model, false);
    }

    /**
     * 角色列表
     *
     * @param values
     * @return
     */
    protected String roleList(List<String> values) {
        StringBuilder result = new StringBuilder("");
        RoleService roleService = SpringContextUtils.getBean(RoleService.class);
        if (!CollectionUtils.isEmpty(values)) {
            for (String roleId : values) {
                Role role = roleService.findOne(Long.valueOf(roleId));
                if (role == null) {
                    continue;
                }
                result.append(role.getDescription());
                result.append(",");
            }
        }
        if (result.length() > 0) {
            result.deleteCharAt(result.length() - 1);
        }
        return result.toString();
    }

    /**
     * 资源列表
     *
     * @param values
     * @return
     */
    protected String resourceList(List<String> values) {
        StringBuilder result = new StringBuilder("");
        if (!CollectionUtils.isEmpty(values)) {
            ResourceService resourceService = SpringContextUtils.getBean(ResourceService.class);
            for (String resourceId : values) {
                Resource resource = resourceService.findOne(Long.valueOf(resourceId));
                if (resource == null) {
                    continue;
                }
                result.append(resource.getName());
                result.append(",");
            }
        }
        if (result.length() > 0) {
            result.deleteCharAt(result.length() - 1);
        }
        return result.toString();
    }

    /**
     * 机构列表
     *
     * @param values
     * @return
     */
    protected String organizationList(List<String> values) {
        StringBuilder result = new StringBuilder("");
        if (!CollectionUtils.isEmpty(values)) {
            OrganizationService organizationService = SpringContextUtils.getBean(OrganizationService.class);
            for (String organizationId : values) {
                Organization organization = organizationService.findOne(Long.valueOf(organizationId));
                if (organization == null) {
                    continue;
                }
                result.append(organization.getName());
                result.append(",");
            }
        }
        if (result.length() > 0) {
            result.deleteCharAt(result.length() - 1);
        }
        return result.toString();
    }

    /**
     * 角色名
     *
     * @param values
     * @return
     */
    protected String roleName(List<String> values) {
        StringBuilder result = new StringBuilder("");
        RoleService roleService = SpringContextUtils.getBean(RoleService.class);
        if (values.size() > 0) {
            Role role = roleService.findOne(Long.valueOf(values.get(0)));
            if (role != null) {
                result.append(role.getRole());
            }
        }

        return result.toString();
    }

    /**
     * 资源名
     *
     * @param values
     * @return
     */
    protected String resourceName(List<String> values) {
        StringBuilder result = new StringBuilder("");
        ResourceService resourceService = SpringContextUtils.getBean(ResourceService.class);
        if (values.size() > 0) {
            Resource resource = resourceService.findOne(Long.valueOf(values.get(0)));
            if (resource != null) {
                result.append(resource.getName());
            }
        }
        return result.toString();
    }

    /**
     * 机构名
     *
     * @param values
     * @return
     */
    protected String organizationName(List<String> values) {
        StringBuilder result = new StringBuilder("");
        OrganizationService organizationService = SpringContextUtils.getBean(OrganizationService.class);
        if (values.size() > 0) {
            Organization organization = organizationService.findOne(Long.valueOf(values.get(0)));
            if (organization != null) {
                result.append(organization.getName());
            }
        }
        return result.toString();
    }
}
